package hhs.poc.activities.scanner;

import hhs.poc.activities.R;
import hhs.poc.activities.scanner.ocr.OCRScannerResult;
import hhs.poc.activities.scanner.ocr.TesseractOCRScanner;
import hhs.poc.activities.scanner.views.CameraPreview;
import hhs.poc.activities.scanner.views.OCRRectangleView;
import hhs.poc.activities.whoiswho.Main;
import hhs.poc.util.utils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.view.Display;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;

public class ScannerActivity extends Activity {

	private LinearLayout _container;
	private ImageView _previewImageView;

	private Size _previewSize;
	private byte[] _previewData;
	private Bitmap _previewBitmap;
	private Camera _camera = null;
	private CameraPreview _preview = null;
	private RelativeLayout _relativeLayout;
	private ImageView _helpImage;
	private Button _captureButton;
	private Button _helpButton;
	private Boolean _helpImageActive = false;

	private TesseractOCRScanner _scanner;

	/** Entry point */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		utils.setTitleBackgroundColor(findViewById(android.R.id.title));
		// setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
		// requestWindowFeature(Window.FEATURE_NO_TITLE);

		if (hasCamera(this)) {

			_camera = getCameraInstance();

			// Recycles same buffer (faster)
			_camera.setPreviewCallbackWithBuffer(previewCallback);

			_previewSize = _camera.getParameters().getPreviewSize();

			int bpp = ImageFormat.getBitsPerPixel(_camera.getParameters()
					.getPreviewFormat());
			bpp = (int) Math.ceil(bpp / 8.0); // 12bpp > 2 ipv 1

			utils.log("ScannerDebug", "Size: " + _previewSize.width + "x"
					+ _previewSize.height + "@" + bpp + " bytes/pixel");
			_previewData = new byte[_previewSize.width * _previewSize.height
					* bpp];
			_camera.addCallbackBuffer(_previewData);

			try {
				_camera.setPreviewDisplay(null);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				utils.log("ScannerDebug", e.getLocalizedMessage());
			}

			toggleFlash(true);

			_scanner = new TesseractOCRScanner();

		} else {
			utils.log("ScannerDebug", "No camera detected.");
			finish(); // End if phone has no (accessible) camera
		}

		WindowManager windowMan = (WindowManager) (getSystemService(Context.WINDOW_SERVICE));
		Display display = windowMan.getDefaultDisplay();
		int h = display.getHeight();

		RelativeLayout.LayoutParams previewParams = new RelativeLayout.LayoutParams(
				0, 0);
		previewParams.leftMargin = 10;
		previewParams.topMargin = 250;
		previewParams.width = 700;
		previewParams.height = 200;

		_captureButton = new Button(this);
		_captureButton.setText("SCAN");

		_helpButton = new Button(this);
		_helpButton.setText("?");

		RelativeLayout.LayoutParams captureParams = new RelativeLayout.LayoutParams(
				new LayoutParams(100, h / 5));
		captureParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
		captureParams.addRule(RelativeLayout.CENTER_VERTICAL);

		RelativeLayout.LayoutParams helpParams = new RelativeLayout.LayoutParams(
				new LayoutParams(100, h / 5));
		helpParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
		helpParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);

		_helpImage = new ImageView(this);
		_helpImage.setImageResource(R.drawable.help);

		// RelativeLayout allows overlaying of Views on top of CameraPreview
		_relativeLayout = new RelativeLayout(this);
		_container = new LinearLayout(this);
		_container.setOrientation(LinearLayout.VERTICAL);

		_previewImageView = new ImageView(this);
		_previewImageView.setBackgroundColor(Color.argb(100, 100, 100, 100));

		_preview = new CameraPreview(this, _camera);
		_relativeLayout.addView(_preview);
		_relativeLayout.addView(new OCRRectangleView(this));

		// _relativeLayout.addView(_previewImageView, previewParams);
		_relativeLayout.addView(_captureButton, captureParams);
		_relativeLayout.addView(_helpButton, helpParams);

		_container.addView(_relativeLayout);

		_captureButton.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				_camera.autoFocus(_autoFocusCallback);
			}
		});

		_helpButton.setOnClickListener(new OnClickListener() {

			public void onClick(View arg0) {
				_helpImageActive = true;
				_relativeLayout.addView(_helpImage);
				_relativeLayout.removeView(_captureButton);
				_relativeLayout.removeView(_helpButton);
				_camera.stopPreview();
			}
		});

		_helpImage.setOnClickListener(new OnClickListener() {

			public void onClick(View arg0) {
				_relativeLayout.removeView(_helpImage);
				_relativeLayout.addView(_captureButton);
				_relativeLayout.addView(_helpButton);
				_camera.startPreview();
			}
		});
		
		setContentView(_container);

		_camera.startPreview();
	}

	private void toggleFlash(Boolean toggle) {
		Parameters params = _camera.getParameters();
		if (toggle == true) {
			params.setFlashMode(Parameters.FLASH_MODE_TORCH);
		} else {
			params.setFlashMode(Parameters.FLASH_MODE_OFF);
		}

		_camera.setParameters(params);
	}

	private AutoFocusCallback _autoFocusCallback = new AutoFocusCallback() {

		public void onAutoFocus(boolean success, Camera camera) {

			_previewBitmap = convertYUVToBitmap(_previewData);

			OCRScannerResult result = _scanner.doScan(_previewBitmap);

			utils.log("ScannerDebug", "Guess: " + result.getDepartment().name()
					+ " " + result.getLevel() + "." + result.getRoom()
					+ " - OCR: " + result.getRawResult());

			_previewImageView.setImageBitmap(_scanner.getLastUsedBitmap());

			String bestGuess = result.toString();

			startWhoIsWho(bestGuess);
		}
	};

	private void startWhoIsWho(String bestGuess) {
		Intent intent = new Intent(this, Main.class);
		intent.putExtra("ocrResult", bestGuess);
		startActivity(intent);
	}

	public Bitmap convertYUVToBitmap(byte[] data) {
		YuvImage yuvImage = new YuvImage(data, ImageFormat.NV21,
				_previewSize.width, _previewSize.height, null);

		ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
		yuvImage.compressToJpeg(new Rect(0, 0, _previewSize.width,
				_previewSize.height), 100, byteStream);

		byte[] imageData = byteStream.toByteArray();

		Bitmap bitmap = BitmapFactory.decodeByteArray(imageData, 0,
				imageData.length);

		return bitmap;
	}

	Camera.PreviewCallback previewCallback = new Camera.PreviewCallback() {
		public void onPreviewFrame(byte[] data, Camera camera) {

			try {
				camera.addCallbackBuffer(_previewData);
			} catch (Exception e) {
				utils.log("ScannerDebug", e.getLocalizedMessage());
			}
		}

	};

	/** Check if this device has a camera */
	private boolean hasCamera(Context context) {
		if (context.getPackageManager().hasSystemFeature(
				PackageManager.FEATURE_CAMERA)) {
			// this device has a camera
			return true;
		} else {
			// no camera on this device
			return false;
		}
	}

	/** A safe way to get an instance of the Camera object. */
	public Camera getCameraInstance() {
		Camera c = null;
		try {
			c = Camera.open(); // attempt to get a Camera instance
		} catch (Exception e) {
			// Camera is not available (in use or does not exist)
			utils.log("ScannerDebug", e.getLocalizedMessage());
		}
		return c; // returns null if camera is unavailable
	}

	private void cleanUp() {

		if (_camera != null) {
			_scanner.release();

			_camera.setPreviewCallbackWithBuffer(null);
			_camera.release(); // release the camera for other applications
			_camera = null;
		}
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();

		cleanUp();
	}

	@Override
	protected void onPause() {
		super.onPause();

		toggleFlash(false);
	}

	@Override
	protected void onResume() {
		super.onResume();

		toggleFlash(true);
	}

	@Override
	public void onBackPressed(){
		if(_helpImageActive == true ){
			_helpImageActive = false;
			_helpImage.performClick();
		} else {
			super.onBackPressed();
		}
		
	}
}